package gui;

import processing.core.PApplet;
import processing.core.PConstants;

public class Slider extends Widget {
	// these define a color palette, that can be used in different ways.
	// use foreColor() and bkgndColor() for drawing.
	private boolean pressed = false;
	private boolean showName = true;
	private boolean showVal = true;
	private float nameTextSize;
	private float valTextSize;
	private float leading = (float)0.9;
	private int decimalPlaces = 2;
	private boolean quantized = false;
	private float quantizeUnit;
	  
	private float dataMin, dataMax;
	private boolean logScale = false;
	private float pos = (float)0.5; // current position, 0..1

	public Slider(PApplet parent_applet, float[] r, float minVal, float maxVal, Object... args) {
		super(parent_applet, r, args);
		neutralColor = pa.color((float)128.);
	    activeColor = pa.color((float)255.);
	    highlightColor = pa.color((float)200.);
	    dataMin = minVal;
	    dataMax = maxVal;
	}
	
	void quantize(float unit) {
		quantized = true;
	    quantizeUnit = unit;
	    if (PApplet.abs(unit-PApplet.round(unit)) < 1e-6) {
	    	decimalPlaces = 0;
	    }
	    setVal(getVal());
	}

	int foreColor() {
	    if (pressed) {
	        return(highlightColor);
	    } else if (over()) {
	        return(activeColor);
	    } else {
	        return(neutralColor);
	    }
	}
	  
	public int bkgndColor() {
	    return backgroundColor;
	}
	  
	private void drawBar() {
		float indicatorWidth = height;
	    pa.rectMode(PConstants.CORNER);
	    pa.noStroke();
	    pa.fill(bkgndColor());
	    pa.rect(x0, y0, width, height);
	    pa.fill(foreColor());
	    float x1 = x0 + (width - indicatorWidth)*getPos();
	    pa.rect(x1, y0, indicatorWidth, height);
	}
	  	  
	private void writeOnLeft(String S) {
	    pa.fill(foreColor());
	    pa.textAlign(PConstants.RIGHT);
	    pa.textLeading(leading*nameTextSize);
	    pa.text(S + " ", x0, y0+height);
	}
	  
	private void writeOnRight(String S) {
	    pa.fill(foreColor());
	    pa.textAlign(PConstants.LEFT);
	    pa.textLeading(leading*valTextSize);
	    pa.text(" " + S, x0 + width, y0 + height);
	}
	  
	private void drawName() {
	    writeOnLeft("name");
	}
	  
	private void drawVal() {
	    writeOnRight(val2string(getVal()));
	}
	  
	public void draw() {
	    if (!hidden) {
	        drawBar();
	        if (showName) {drawName();}
	        if (showVal) {drawVal();}
	    }
	}

	public void mousePressed() {
		// If mouse pressed over slider, move the slider
		float indicatorWidth = height;
        setPos((pa.mouseX - x0)/(width - indicatorWidth));
	}

	public void mouseDragged() {
		// If mouse dragged over slider, move the slider.
		float indicatorWidth = height;
        setPos((pa.mouseX - x0)/(width - indicatorWidth));
	}
	  
	// use these four routines for reading & changing the position of the slider.
	// pos = relative position, 0..1
	// val = value in data units  
	public float getPos() {return pos;}
	public float getVal() {return pos2val(getPos());}
	public void setPos(float p) {pos = PApplet.constrain(p, 0, 1);}
	public void setVal(float v) {setPos(val2pos(v));}

	// these are general conversion functions, that can be used for values other than the current one
	// e.g., to find out the current min and max values allowed, use pos2val(0) and pos2val(1)
	String val2string(float v) {
	    if (decimalPlaces==0) {
	        return PApplet.str(PApplet.round(v));
	    } else {
	        float p = PApplet.pow(10, decimalPlaces);
	        return PApplet.str(PApplet.round(v*p)/(float)p);
	    }
	}
	  
	float val2pos(float v) {
	    float p;
	    if (quantized) {
	        v = PApplet.round(v/quantizeUnit)*quantizeUnit;
	    }
	    if (logScale) {
	        p = (PApplet.log(v)-PApplet.log(dataMin))/(PApplet.log(dataMax)-PApplet.log(dataMin));
	    } else {
	        p = (v-dataMin)/(dataMax-dataMin);
	    }
//	    if (isnan(p)) {
//	      return 0;
//	    } else {
	      return p;
//	    }
	}
	  
	float pos2val(float p) {
	    float v;
	    if (logScale) {
	        v = dataMin * PApplet.pow(dataMax/dataMin, p);
	    } else {
	        v = dataMin + (dataMax-dataMin) * p;
	    }
	    if (quantized) {
	        v = PApplet.round(v/quantizeUnit)*quantizeUnit;
	    }
	    return v;
	}  

}
